﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using Qiang.Data;
using Qiang.Topology.Geometries;

using Point = System.Drawing.Point;

namespace Qiang.Controls
{    
    public partial class MapControl : UserControl
    {

        public MapControl()
        {
            InitializeComponent();
            this.Configure();
        }

        private void Configure()
        {
            this._map = new Map(this, new Extent(-180, -90, 180, 90));

        }

        
        # region 属性字段


        MapFunction _currentFunction;

        /// <summary>
        /// 当前工具.
        /// </summary>
        public MapFunction CurrentFunction
        {
            get { return _currentFunction; }
            set 
            {
                if (value != null)
                {
                    if (_currentFunction != null) _currentFunction.Deactive();
                    _currentFunction = value;
                    _currentFunction.MapControl = this;
                    this.Cursor = _currentFunction.Cursor;
                    _currentFunction.Active();
                }
            }
        }




        private double _scaleFactor = 0.1;

        /// <summary>
        /// 缩放系数
        /// </summary>
        public double ScaleFactor
        {
            get { return _scaleFactor; }
            set 
            {
                _scaleFactor = value;

                if (_scaleFactor > 1) _scaleFactor = 1;
                if (_scaleFactor < 0.001) _scaleFactor = 0.05;

            }
        }


        private Size _oldParentSize;
        private bool _parentResizing = false;



        private Map _map;

        //辅助绘制图层显示到map控件上
        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Map Map
        {
            get { return _map; }
            set 
            {
                _map = value;
                _map.InitializeBackBitmap();
            }
        }


        # endregion


        # region 私有方法

      

        # endregion
        

        # region 图层控制方法

        public IMapLayer AddVectorLayer(VectorSet vectorData)
        {
            MapVectorLayer mapLayer = new MapVectorLayer(vectorData);
            return this.AddLayer(mapLayer); 
        }


        public IMapLayer AddLayer(IMapLayer mapLayer)
        {
            this._map.Layers.Add(mapLayer);
            this._map.InitializeBackBitmap();
            if (this._map.Layers.Layers.Count == 1)
            {
                this.ZoomToMaxExtent();
            }            
            return mapLayer;
        }


        public IMapLayer AddImageLayer(IImageDataset ImageData)
        {
            MapImageLayer layer = new MapImageLayer(ImageData);
            return this.AddLayer(layer);
        }
        

        public IMapLayer GetLayer(int index)
        {
            return this._map.Layers.GetLayer(index);
        }

        /// <summary>
        /// 获取所有图层
        /// </summary>
        /// <returns></returns>
        public List<IMapLayer> GetAllLayers()
        {
            return this._map.Layers.Layers;
        }

        /// <summary>
        /// 清空所有图层
        /// </summary>
        public void RemoveAllLayers()
        {
            this._map.Layers.RemoveAllLayers();
            this.Refresh();
        }


        # endregion
        

        # region 坐标转换

        public Point ProjToPixel(Coordinate point)
        {
            return this._map.ProjToPixel(point);
        }

        public Coordinate PixelToProj(Point point)
        {
            return this._map.PixelToProj(point);
        }


        public Extent PixelToProj(Rectangle rect)
        {
            return this._map.PixelToProj(rect);
        }

        public Rectangle ProjToPixel(Extent ext)
        {
            return this._map.ProjToPixel(ext);
        }

        # endregion


        public void ZoomToMaxExtent()
        {
            this._map.ZoomToMaxExtent();
            this.Invalidate();
        }



        /// <summary>
        /// 获取当前窗口显示的位图
        /// </summary>
        /// <returns></returns>
        public Bitmap GetBitMap()
        {
            Bitmap map = new Bitmap(this.Width, this.Height);
            Graphics g = Graphics.FromImage(map);
            g.DrawImage(this._map.BufferImage, new Rectangle(0, 0, this.Width, this.Height));
            return map;
        }



        
        # region 继承的方法


        protected override void OnLoad(EventArgs e)
        {
            //首先要订阅键盘事件


            //改变控件大小事件
            if (this.ParentForm != null)
            {
                this.ParentForm.ResizeBegin += this.ParentFormResizeBegin;
                this.ParentForm.ResizeEnd += ParentFormResizeEnd;
                this.ParentForm.KeyDown += ParentForm_KeyDown;
                this.ParentForm.KeyUp += ParentForm_KeyUp;
            }

        }

        void ParentForm_KeyUp(object sender, KeyEventArgs e)
        {
            this.OnKeyDown(e);
        }

        void ParentForm_KeyDown(object sender, KeyEventArgs e)
        {
            this.OnKeyUp(e);
        }

        private void ParentFormResizeBegin(object sender, EventArgs e)
        {
            this._parentResizing = true;
        }

        private void ParentFormResizeEnd(object sender, EventArgs e)
        {
            this._parentResizing = false;
            if (this._map == null) return;
            if (this.ParentForm.Size == this._oldParentSize) return;
            this._oldParentSize = this.ParentForm.Size;
            Rectangle CurrentView = new Rectangle(0, 0, this.Width, this.Height);
            this._map.ResetExtent(CurrentView); //重新设置视图区域，会触发重新绘制图层方法
            this.Invalidate();
        }

        private void ParentFormKeyDown()
        {
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            if (this._map != null)
            {
                if (this._parentResizing == false)
                {
                    Rectangle CurrentView = new Rectangle(0, 0, this.Width, this.Height);
                    this._map.ResetExtent(CurrentView);
                }
            }
        }

     

        protected override void OnPaint(PaintEventArgs e)
        {
            //触发onPaint方法的事件主要是控件的Invilidate()方法，Invilidate（）默认时是重绘整个窗体，所以e.ClipRectangle的范围也是窗体控件的范围
            //Invilidate还有一个重载方法Invilidate（Rectancle）,这个重载方法是重绘窗体控件的指定矩形区域，此时e.ClipRectangle即重绘的区域，所以下面要对e.ClipRectangle做一些操做

            Rectangle clipRect = e.ClipRectangle;
            Bitmap temBitmap = new Bitmap(clipRect .Width ,clipRect .Height ,System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            Graphics g = Graphics.FromImage(temBitmap);
            g.FillRectangle(new SolidBrush(this.BackColor), new Rectangle(0, 0, temBitmap.Width, temBitmap.Height));
            //g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

            System.Drawing.Drawing2D.Matrix m = new System.Drawing.Drawing2D.Matrix();
            m.Translate(-clipRect.X, -clipRect.Y);
            g.Transform = m;  //将画笔位置放到当前绘制区域

            this._map.DrawBackBitmap(new PaintEventArgs(g, e.ClipRectangle)); //属于始终绘制临时视图区域的动态的图层信息.

            MapPaintArgs args = new MapPaintArgs(g, clipRect, this);

            if (_currentFunction != null)
            {
                _currentFunction.Paint(args);
            }

            PaintEventArgs pe = new PaintEventArgs(g, e.ClipRectangle);
            base.OnPaint(pe);

            g.Dispose();

            if (this._parentResizing)
            {
            }
            else
            {
                //this.CreateGraphics().DrawImageUnscaled(temBitmap, clipRect.X, clipRect.Y); //绘制到控件上
                e.Graphics.DrawImageUnscaled(temBitmap, clipRect.X, clipRect.Y); //绘制到控件上
            }

            temBitmap.Dispose();
        }


        //注意：关于键盘事件，这里不但实现控件本身的键盘事件，还要实现控件父窗体的键盘事件。这样就不能像重载鼠标操做一样重载键盘操做的方法了，而采用订阅事件的方法
        //先订阅本身的键盘事件，如果存在父窗体则同时订阅父窗体的键盘事件

        protected override void OnMouseClick(MouseEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoMouseClick(new MapMouseArgs(e, this));
            }

            base.OnMouseClick(e);
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoMouseDown(new MapMouseArgs(e, this));
            }

            base.OnMouseDown(e);
        }

        protected override void OnMouseUp(MouseEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoMouseUp(new MapMouseArgs(e, this));
            }

            base.OnMouseUp(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoMouseMove(new MapMouseArgs(e, this));
            }

            base.OnMouseMove(e);
        }

        protected override void OnMouseWheel(MouseEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoMouseWheel(new MapMouseArgs(e, this));
            }

            base.OnMouseWheel(e);
        }

        protected override void OnKeyDown(KeyEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoKeyDown(e);
            }
            base.OnKeyDown(e);
        }
        
        protected override void OnKeyUp(KeyEventArgs e)
        {
            if (_currentFunction != null)
            {
                _currentFunction.DoKeyUp(e);
            }
            base.OnKeyUp(e);
        }


        public override void Refresh()
        {
            this._map.InitializeBackBitmap();
            base.Refresh();
            this.Invalidate();
        }


        # endregion
                       

    }
}
